package com.jgz;

/**
 * ================================================
 * 作者:Je(揭光智)     联系方式:QQ:364049613
 * 版本:
 * 创建日期:2018/7/31
 * 描述:
 * 修订历史：
 * ================================================
 */
public class ArrayBag<T> implements IBag<T> {

    /**
     * ArrayBag的大小
     */
    private int size;

    /**
     * 默认初始容量
     */
    private static final int DEFAULT_CAPACITY = 10;


    /**
     * 用于空实例的共享空数组实例.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};


    /**
     * 用于默认大小的空实例的共享空数组实例.
     * 我们将它与{@code EMPTY_ELEMENTDATA}区别开来,以了解在添加第一个元素时需要膨胀多少.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 数组缓冲区,里面存储的是ArrayBag的元素.
     * ArrayBag的容量是这个数组缓冲区的长度.
     */
    private Object[] elementData;


    public ArrayBag(int initialCapacity) {
        if (initialCapacity > 0) {
            elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("非法参数initialCapacity:" + initialCapacity);
        }
    }

    public ArrayBag() {
        this(DEFAULT_CAPACITY);
    }


    @Override
    public boolean add(T elem) {
        if (isArrayFull()) return false;
        elementData[size++] = elem;
        return true;
    }

    @Override
    public Object[] toArray() {
        return elementData;
        // return Arrays.copyOf(elementData, size);
    }


    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isArrayFull() {
        return size >= DEFAULT_CAPACITY;
    }

    @Override
    public int size() {
        return size;
    }

    public int length() {
        return elementData.length;
    }


    @Override
    public boolean contains(T elem) {
        for (int i = 0; i < size; ++i) {
            if (elem == elementData[i]) return true;
        }
        return false;
    }

    @Override
    public void clear() {
        for (int i = 0; i < size; ++i) {
            elementData[i] = null;
        }
        size = 0;
    }

    @Override
    public T remove(int index) {
        rangeCheck(index);
        fastRemove(index);
        return null;
    }

    @Override
    public boolean remove(T elem) {
        if (elem == null) {
            for (int index = 0; index < size; ++index) {
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
            }
        } else {
            for (int index = 0; index < size; ++index) {
                if (elem.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 使用JVM的数组复制方法,这是Java性能优化的技巧
     */
    private void fastRemove(int index) {
        int numMoved = size - 1 - index;//需要移动的次数
        if (numMoved > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, numMoved);
        }
        elementData[--size] = null;
    }

    /**
     * 检查索引的范围
     */
    private void rangeCheck(int index) {
        if (index >= size) throw new IndexOutOfBoundsException("索引越界:" + index);
    }

    @SuppressWarnings("unchecked")
    private T elementData(int index){
        return (T) elementData[index];
    }


    @Override
    public T get(int index) {
        rangeCheck(index);
        return elementData(index);
    }


    @Override
    public int indexOf(T elem) {
        if (elem == null){
            for (int index = 0; index < size; index++) {
                if (elementData[index] == null) return index;
            }
        } else {
            for (int index = 0; index < size; index++) {
                if (elem.equals(elementData[index])) return index;
            }
        }

        return -1;
    }

    @Override
    public int lastIndexOf(T elem) {

        if (elem == null){
            for (int index = size - 1; index >= 0; index--) {
                if (elementData[index] == null) return index;
            }
        } else {
            for (int index = size - 1; index >= 0; index--) {
                if (elem.equals(elementData[index])) return index;
            }
        }
        return -1;
    }
}
